#include <string>
#include <string.h>
#include "net/buffer.h"
#include "ut_test.h"


using namespace rr::nio;

static void Test_1()
{
    size_t init_size = 1024;
    Buffer buffer(1024);

    UT_CHECK(0 == buffer.ReadableBytes());
    UT_CHECK(init_size == buffer.WritableBytes());
    UT_CHECK(Buffer::kCheapPrepend == buffer.PrependableBytes());
}

static void Test_2()
{
    // to test max size
    int32_t max_size = 2*1024*1024;
    int32_t size = 64*1024;
    int32_t count = max_size / size;

    Buffer buffer(size, max_size);

    for(int32_t i = 0; i < count; i++) {
        UT_CHECK(buffer.EnsureWritableBytes(size));
        buffer.HasWritten(size);
    }
    printf("Test_2 EnsureWritableBytes max\n");
    UT_CHECK(!buffer.EnsureWritableBytes(size));

    buffer.Clear();
    UT_CHECK(buffer.EnsureWritableBytes(size));
}

static void Test_3()
{
    printf("Test_3\n");
    Buffer buffer(1024);

    size_t write_len = 100;
    UT_CHECK(buffer.EnsureWritableBytes(write_len));
    buffer.HasWritten(write_len);
    size_t remain_len = write_len;

    size_t read_len = 40;
    UT_CHECK((read_len <= buffer.ReadableBytes()))
    buffer.Retrieve(read_len);

    remain_len -= read_len;
    UT_CHECK((buffer.ReadableBytes() == remain_len));

    buffer.Retrieve(read_len);
    remain_len -= read_len;
    UT_CHECK((buffer.ReadableBytes() == remain_len));
}

static void Test_4()
{
    printf("Test_4\n");
    Buffer buffer(1024);

    size_t write_len = 100;
    UT_CHECK(buffer.EnsureWritableBytes(write_len));
    buffer.HasWritten(write_len);
    size_t remain_len = write_len;

    size_t read_len = 40;
    UT_CHECK((read_len <= buffer.ReadableBytes()))
    buffer.Retrieve(read_len);

    remain_len -= read_len;
    UT_CHECK((buffer.ReadableBytes() == remain_len));

    buffer.Retrieve(read_len);
    remain_len -= read_len;
    UT_CHECK((buffer.ReadableBytes() == remain_len));
}

static void Test_5()
{
    printf("Test_5\n");
    Buffer buffer(10);

    std::string str_src = "0123456789";
    UT_CHECK(buffer.Append(str_src.c_str(), str_src.length()));
    UT_CHECK(!memcmp(str_src.c_str(), buffer.Peek(), str_src.length()));
    UT_CHECK((buffer.ReadableBytes() == str_src.length()));
    UT_CHECK((buffer.WritableBytes() == 10 - str_src.length()));

    size_t read_len = 6;
    buffer.Retrieve(read_len);
    UT_CHECK((buffer.ReadableBytes() == 10 - read_len));
    UT_CHECK(!memcmp(str_src.substr(read_len).c_str(), buffer.Peek(), buffer.ReadableBytes()));

    std::string str2 = "abcdef";
    UT_CHECK(buffer.Append(str2.c_str(), str2.length()));
    std::string str_dst = str_src.substr(read_len).c_str() + str2;
    UT_CHECK(!memcmp(str_dst.c_str(), buffer.Peek(), buffer.ReadableBytes()));

    printf("str:%.*s\n", (int32_t)buffer.ReadableBytes(), buffer.Peek());
}


void TestBuffer()
{
    printf("start TestBuffer\n");
    Test_1();

    Test_2();

    Test_3();

    Test_4();

    Test_5();
} 